package com.tedu.shoot;

import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Date：2021年08月
 * Author：程Sir
 * Content:
 * 这是游戏的场景测试类
 */
public class World extends JPanel {
    // 设置画框的大小
    public static final int WIDTH = 512;
    public static final int HEIGHT = 768;
    // 分数
    public int score;

    //声明的第一种状态：开始
    public static final int START = 0;
    //声明的第二种状态：运行
    public static final int RUNNING = 1;
    //声明的第三种状态：暂停
    public static final int PURSE = 2;
    //声明的第四种状态：结束
    public static final int GAMEOVER = 3;
    // 表示游戏的初始状态
    public int state = START;


    public Hero hero = new Hero();;
    public Sky sky = new Sky();
    public Bullet[] bullet ={};

    //声明了一个敌人数组，可以存放：Bee/BigAirplane/airplane
    public FlyingObject[] enemies={};

    /**
     * 生成敌人对象方法
     * @return 返回生成的敌人对象
     */
    public FlyingObject nextEnemy(){
        Random random = new Random();
        int index = random.nextInt(20);
        if (index <=5){ // 随机数在0-5生成的是蜜蜂
            return new Bee();
        }else if(index<=13){// 随机数在5-13生成的是小敌人
            return new Airplane();
        }else{ // 随机数在13-20生成的是大敌人
            return new BigAirplane();
        }
    }

    // 执行的方法
    public void action(){
        // 鼠标监听器对象
        MouseAdapter mouseAdapter = new MouseAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                if (state == RUNNING){
                    // 获取鼠标的坐标
                    int x = e.getX();
                    int y = e.getY();
                    // 将获取到的坐标值传给英雄机
                    hero.move(x,y);
                }
            }

            @Override
            public void mouseClicked(MouseEvent e) {
                switch (state){
                    case START: // 如果是开始状态，点击鼠标了就变为运行状态
                        state = RUNNING;
                        break;
                    case RUNNING: // 如果是运行状态，点击鼠标就发射子弹
                        // 拿到英雄射击的子弹
                        Bullet[] b = hero.nextBullet();
                        // 将当前子弹数组进行扩容
                        bullet = Arrays.copyOf(bullet, bullet.length+b.length);
                        // 将英雄射击的子弹数组放置到扩容好的子弹数组中
                        System.arraycopy(b,0,bullet,bullet.length-b.length,b.length);
                }
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                if (state == PURSE){ // 如果状态是暂停，当鼠标移入的时候，切为 运行状态
                    state =  RUNNING;
                }
            }

            @Override
            public void mouseExited(MouseEvent e) {
                if(state == RUNNING){ // 如果是运行状态，当鼠标移出的时候，切为 暂停状态
                    state = PURSE;
                }
            }
        };
        // 将鼠标监听器对象添加到面板上
        this.addMouseListener(mouseAdapter);
        // 给当前的窗口对象添加处理鼠标移动的事件
        this.addMouseMotionListener(mouseAdapter);

        // java中的定时器
        Timer timer = new Timer();
        // 调用定时器的执行方法【时间表】
        timer.schedule(new TimerTask() {
            @Override
            public void run() { // 指定制定的任务

                if(state == RUNNING){
                    // 敌人入场的方法
                    enterAction();
                    // 飞行物移动的方法
                    stepAction();
                    // 子弹入场的方法
//                    shootAction();
                    // 越界判断
                    outOfBoundsAction();
                    // 英雄碰撞判断
                    heroHitAction();
                    // 子弹碰撞判断
                    bulletHitAction();
                    // 重新画界面的内容
                }
                repaint();

            }
        },10,10); // 第一个10ms表示的是run方法相较于schedule方法延迟的时间，第二个10ms表示的是每10ms执行一次run。
    }

    /**
     * 子弹碰撞的方法
     */
    private void bulletHitAction() {
        // 变量所有的子弹
        for (int i = 0; i <bullet.length ; i++) {
            // 获取每一个子弹
            Bullet b = bullet[i];
            // 变量所有的敌人数组
            for (int j = 0; j <enemies.length ; j++) {
                // 获取每一个敌人
                FlyingObject f = enemies[j];
                // 判断条件
                if (b.isLive() && f.isLive() && b.isHit(f) ){
                    // 让子弹死亡
                    b.goDead();
                    // 让敌人死亡
                    f.goDead();
                    // 如果敌人是：大敌人和小敌人
                    if (f instanceof Enemy){
                        Enemy e = (Enemy)f;
                        score += e.getScore();
                    }else{//如果敌人是：小蜜蜂
                        Award a = (Award)f;
                        int type = a.getType();
                        switch ( type ){
                            case Award.DOUBLE_FIRE:
                                hero.addFire();
                                break;
                            case Award.LIFE:
                                hero.addLife();
                                break;
                        }
                    }
                }
            }
        }
    }

    /**
     * 英雄碰撞的方法
     */
    private void heroHitAction() {
        // 遍历敌人数组
        for (int i = 0; i <enemies.length ; i++) {
            FlyingObject f = enemies[i];
            if(f.isLive() && hero.isLive() && hero.isHit(f) ){
                System.out.println("发生碰撞了！");
                // 让敌人死掉
                f.goDead();
                // 英雄要减命
                hero.substractLife();
                // 英雄清除双倍火力值
                hero.clearFire();
            }
        }
    }

    // 声明一个计数的变量，用来控制敌人入场的频率
    int enterIndex = 0;
    /**
     * 敌人入场的方法
     */
    private void enterAction() {
        enterIndex ++;
        if(enterIndex % 40 == 0){ // 每 10*40 = 400ms执行一次if内容
            //生成一个敌人
            FlyingObject f = nextEnemy();
            // 将当前敌人数组进行扩容一个位置
            enemies = Arrays.copyOf(enemies, enemies.length+1);
            // 将生成的敌人放入扩容的位置
            enemies[enemies.length-1] = f;
        System.out.println("敌人数组的长度："+enemies.length);
        }
    }

    // 声明一个计数的变量，用来控制敌人入场的频率
    int bulletIndex = 0;
//    /**
//     * 子弹入场的方法
//     */
//    private void shootAction(){
//        bulletIndex++;
//        if(bulletIndex %30 == 0){ // 每 10*30 = 300ms执行一次if内容
//            // 拿到英雄射击的子弹
//            Bullet[] b = hero.nextBullet();
//            // 将当前子弹数组进行扩容
//            bullet = Arrays.copyOf(bullet, bullet.length+b.length);
//            // 将英雄射击的子弹数组放置到扩容好的子弹数组中
//            System.arraycopy(b,0,bullet,bullet.length-b.length,b.length);
//        System.out.println("子弹的长度："+enemies.length);
//        }
//    }

    /**
     * 飞行物移动
     */
    public void stepAction(){
        // 天空（背景）移动
        sky.step();
        // 敌人移动
        for (int i = 0; i <enemies.length ; i++) {
            enemies[i].step();
        }
        // 子弹移动
        for (int i = 0; i < bullet.length; i++) {
            bullet[i].step();
        }
    }

    /**
     * 缩容敌人对象: 出界的对象 和 碰撞的对象
     */
    public void outOfBoundsAction(){
        // 定义存储没有越界数组的下标变量
        int index = 0;
        // 创建一个敌人数组同等长度的数组对象，用来存储没有出界的敌人对象
        FlyingObject[] flyingObjects = new FlyingObject[enemies.length];
        for (int i = 0; i <enemies.length ; i++) {
            // 获取每一个敌人对象
            FlyingObject f = enemies[i];
            if(!f.isOutBound() && !f.isRemove()){
//                flyingObjects[index] = f;
//                index ++;
                flyingObjects[index++] = f; // 跟上面两行代码等价
            }
        }
        enemies = Arrays.copyOf(flyingObjects,index);

        int index1 = 0;
        Bullet[] bs = new Bullet[bullet.length];
        for (int i = 0; i <bullet.length ; i++) {
            // 获取每一个子弹对象
            Bullet b = bullet[i];
            if (!b.isOutBound() && !b.isRemove()){
                bs[index1++] = b;
            }
        }
        bullet = Arrays.copyOf(bs,index1);

    }

    /**
     * 这是继承的画画方法，对其进行重写
     * @param g 表示画笔
     */
    @Override
    public void paint(Graphics g) {
        // 画天空（背景）
        sky.paint(g);
        // 画敌人
        for (int i = 0; i <enemies.length ; i++) {
            enemies[i].paint(g);
        }
        // 画英雄
        hero.paint(g);
        // 画子弹
        for (int i = 0; i <bullet.length ; i++) {
            bullet[i].paint(g);
        }
//        System.out.println("画画的方法执行完毕！");

    }

    public static void main(String[] args) {
        // 创建画框对象
        JFrame jFrame = new JFrame("Java基础项目-程sir小课堂");
        // 创建一个容器对象 Component
        World world = new World();
        // 将画板（容器）放置到画框上
        jFrame.add(world);
        // 设置画框显示方式
        jFrame.setVisible(true);
        // 设置画框的尺寸
        jFrame.setSize(WIDTH,HEIGHT);
        // 设置窗口的位置
        jFrame.setLocationRelativeTo(null);
        // 设置关闭方式
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        world.action();
    }
}
